<?php

namespace app\common\library;


class Sign
{
    const VERSION = '6.0.5';

    public static $instance ;
    //开始有签到功能的日期
    public static $startDate = '2018-09-20';

    /**
     * @title 单例调用
     * @description 单例调用
     * @author Admin ldy
     * @time 2018/9/25  12:22
     */
    public static function getInstance(){
        if (Sign::$instance == null){
            Sign::$instance = new \app\common\library\Sign;
            return Sign::$instance;
        }else{
            return Sign::$instance;
        }
    }

    public function __construct(){
        //初始化
    }

    public function getStartDate(){
        return Sign::$startDate;
    }

    /**
     * @title 用户签到，今天
     * @description 用户签到，今天
     * @author Admin ldy
     * @param name:uid  type:string require:1 default:1 desc:
     * @time 2018/9/28  14:41
     */
    public static function recordToday($uid){
//        $redis = new \Redis();
//        $redis->connect('127.0.0.1');
        //记录有uid的key
        $cacheKey = sprintf("sign_%d", $uid);
        //开始有签到功能的日期
//        $startDate = '2018-09-20';
        //今天的日期
//        $todayDate = Date('Y-m-d');
//        //计算offset
//        $startTime = strtotime(Sign::$startDate);
//        $todayTime = strtotime($todayDate);
//        $offset = floor(($todayTime - $startTime) / 86400);
        $offset = Sign::calcTodayOffset();
//        echo "今天是第{$offset}天" . PHP_EOL;
        //签到
        ////一年一个用户会占用多少空间呢？大约365/8=45.625个字节，好小，有木有被惊呆？
        Sign::getRedis()->setBit($cacheKey, $offset, 1);
        //查询签到情况,$offset为第几天
//        $bitStatus = $redis->getBit($cacheKey, $offset);
//        echo 1 == $bitStatus ? '今天已经签到啦' : '还没有签到呢';
//        echo PHP_EOL;
        //计算总签到次数
//        echo $redis->bitCount($cacheKey) . PHP_EOL;
    }

    /**
     * @title 给用户的某一天签到
     * @description 给用户的某一天签到
     * @author Admin ldy
     * @param name:uid  type:string require:1 default:1 desc:用户id
     * @param name:$somedate  type:string require:1 default:1 desc:格式为'2018-09-20'  Date('Y-m-d');
     * @time 2018/9/28  15:07
     * @return int：是否成功
     */
    public static function recordSomeDate($uid,$somedate){
        return Sign::getRedis()->setBit(Sign::getCacheKey($uid), Sign::calcOffsetByDate($somedate), 1);
    }

    /**
     * @title 获取缓存的key
     * @description 获取缓存的key
     * @author Admin ldy
     * @param name:uid  type:string require:1 default:1 desc:
     * @time 2018/9/28  15:09
     * @return string
     */
    public static function getCacheKey($uid){
        return sprintf("sign_%d", $uid);
    }

    /**
     * @title 获取某一天的签到情况
     * @description 获取某一天的签到情况
     * @author Admin ldy
     * @param name:uid  type:string require:1 default:1 desc:用户id
     * @param name:$someDate  type:string require:1 default:1 desc:格式为'2018-09-20'  Date('Y-m-d');
     * @time 2018/9/28  15:09
     * @return int
     */
    public static function getStatusByDate($uid,$someDate){
        //查询签到情况
        return Sign::getRedis()->getBit(Sign::getCacheKey($uid),Sign::calcOffsetByDate($someDate));
    }

    /**
     * @title 获取用户的总签到数
     * @description 获取用户的总签到数
     * @author Admin ldy
     * @param name:uid  type:string require:1 default:1 desc:用户id
     * @time 2018/9/28  15:10
     * @return int:用户的总签到数
     */
    public static function countSign($uid){
        //计算总签到次数
        return Sign::getRedis()->bitCount(Sign::getCacheKey($uid));
    }

    /**
     * @title 计算从发布签到功能开始，今天是第几天
     * @description 计算从发布签到功能开始，今天是第几天。可以用来下一步计算，查询某天的签到情况。
     * @author Admin ldy
     * @time 2018/9/28  14:50
     * @return float
     */
    public static function calcTodayOffset(){
        //开始有签到功能的日期
//        $startDate = '2018-09-20';
        //今天的日期
        $todayDate = Date('Y-m-d');
        //计算offset
        $startTime = strtotime(Sign::$startDate);
        $todayTime = strtotime($todayDate);
        return $offset = floor(($todayTime - $startTime) / 86400);
    }

    /**
     * @title 计算查看日期的offset
     * @description 计算查看日期的offset。只能查询开始有签到功能后，当前日期前的日期数据。
     * @author Admin ldy
     * @param name:$showDate  type:string require:1 default:1 desc:
     * @time 2018/9/28  14:55
     * @return float:结果需要大于0，否则会报错。只能查询开始有签到功能后，当前日期前的日期数据。
     */
    public static function calcOffsetByDate($showDate){
        //计算offset
        $startTime = strtotime(Sign::$startDate);
        $todayTime = strtotime($showDate);
        return $offset = floor(($todayTime - $startTime) / 86400);
    }

    /**
     * @title 获取redis实例
     * @description 获取redis实例
     * @author Admin ldy
     * @time 2018/9/28  15:11
     * @return \Redis
     */
    public static function getRedis(){
        $redis = new \Redis();
        $redis->connect('127.0.0.1');
        $redis->auth('!123qweAb');
        return $redis;
    }

    /**
     * @title 检查今天是否已经签到
     * @description 检查今天是否已经签到
     * @author Admin ldy
     * @param name:uid  type:string require:1 default:1 desc:
     * @time 2018/9/28  15:12
     * @return ReFail|ReSuccess
     */
    public static function isSignToday($uid){
//        $redis = new \Redis();
//        $redis->connect('127.0.0.1');
        //记录有uid的key
        $cacheKey = sprintf("sign_%d", $uid);
        //开始有签到功能的日期
//        $startDate = '2018-09-20';
        //今天的日期
        $todayDate = Date('Y-m-d');
        //计算offset
        $startTime = strtotime(Sign::$startDate);
        $todayTime = strtotime($todayDate);
        $offset = floor(($todayTime - $startTime) / 86400);
        $bitStatus = Sign::getRedis()->getBit($cacheKey, $offset);

        return $bitStatus;
//        if (1 == $bitStatus){
//            return new ReSuccess('今天已经签到啦',1);
//        }else{
//            return new ReFail('还没有签到呢');
//        }
    }

    /**
     * @title 获取两个日期之间的日期
     * @description 获取两个日期之间的日期,返回数组
     * @author Admin ldy
     * @param name:$start  type:string require:1 default:1 desc:开始日期 Y-m-d
     * @param name:$end  type:string require:1 default:1 desc:结束日期 Y-m-d
     * @time 2018/10/22  14:00
     * @return array
     */
    public static function prDates($start,$end){
        $datas=array();
        $dt_start = strtotime($start);
        $dt_end = strtotime($end);
        while ($dt_start<=$dt_end){
            array_push($datas,date('Y-m-d',$dt_start));
//            echo date('Y-m-d',$dt_start)."\n";
            $dt_start = strtotime('+1 day',$dt_start);
        }
        return $datas;
    }


    /**
     * @title 查询用户的签到情况
     * @description 查询用户的签到情况，返回数组
     * @author Admin ldy
     * @param name:$uid  type:string require:1 default:1 desc:用户id
     * @param name:$start  type:string require:1 default:1 desc:开始日期Y-m-d
     * @param name:$end  type:string require:1 default:1 desc:结束日期Y-m-d
     * @time 2018/10/22  14:01
     * @return array
     */
    public static function getUserSignDataBy($uid,$start,$end){
        $datas=array();
        $dt_start = strtotime($start);
        $dt_end = strtotime($end);
        while ($dt_start<=$dt_end){
            $dateTemp = date('Y-m-d',$dt_start);
            $signStatus=Sign::getStatusByDate($uid,$dateTemp);
            $tempObj = array(
                'date'=>$dateTemp,
                'signStatus'=>$signStatus,
            );
            array_push($datas,$tempObj);
            $dt_start = strtotime('+1 day',$dt_start);
        }
        return $datas;
    }

    /**
     * @title 获取用户最近7天的签到情况
     * @description 获取用户最近7天的签到情况
     * @author Admin ldy
     * @param name:$uid  type:string require:1 default:1 desc:
     * @time 2018/12/19  12:39
     * @return array
     */
    public static function getUserSignDataNearly($uid){
        $end = Date('Y-m-d');//今天
        $start = date('Y-m-d', strtotime('-7 days'));//七天前
        return Sign::getUserSignDataBy($uid,$start,$end);
    }

    /**
     * @title 检查该用户是否活跃
     * @description 检查该用户是否活跃，即七天内是否有签到
     * @author Admin ldy
     * @param name:$uid  type:string require:1 default:1 desc:
     * @time 2018/10/22  14:04
     * @return bool
     */
    public static function checkUserActive($uid){
        $end = Date('Y-m-d');//今天
        $start = date('Y-m-d', strtotime('-7 days'));//七天前
        $result = false;
        $dt_start = strtotime($start);
        $dt_end = strtotime($end);
        //从七天前开始查，如果有一天登录使用过，则说明该用户为活跃用户！
        while ($dt_start<=$dt_end){
            $dateTemp = date('Y-m-d',$dt_start);
            $signStatus=Sign::getStatusByDate($uid,$dateTemp);
            if ($signStatus==1){
                $result = true;
                break;
            }
            $dt_start = strtotime('+1 day',$dt_start);
        }
        return $result;
    }


}
